home *** CD-ROM | disk | FTP | other *** search
- program investigate_header; {Investigate a Windows 3.1 EXE header}
- uses crt;
-
- type
- OLD_HEADER_TYPE =record
- ID_Word :word; {Better be MZ}
- Last_Page_Size :word; {Size of last page}
- Page_Count :word; {512 byte blocks}
- Rel_Table_Entries :word; {Entries in relocation table}
- Header_Size :word; {16 byte paragraphs}
- MINALLOC :word; {Min size program needs, 16 byte paragraphs}
- MAXALLOC :word; {Max size program will take, 16 byte paragraphs}
- Init_SS :word; {Initial stack (relocated)}
- Init_SP :word;
- Checksum :word; {Normally not used}
- Init_IP :word; {Entry point (relocated)}
- Init_CS :word;
- Reloc_Table_Offset :word; {Location of relocation table, from start of file}
- {If >=40H, then value at 3CH is offset to new style header}
- Overlay_No :word; {Overlay number, 0 for programs}
- Filler :array[$1C..$3B] of byte;
- New_Header_Offset :word;
- end;
-
- NEW_HEADER_TYPE =record
- Signature :word; {00 Better be NE}
- Linker_Version :byte; {02 Self-explanatory}
- Linker_Revision :byte; {03}
- Entry_Table_Offset :word; {04}
- Entry_Table_Length :word; {06}
- Reserved1a :word; {08}
- Reserved1b :word; {0A}
- Flags :word; {0C}
- Automatic_Data_Seg :word; {0E 0 if SINGLEDATA and MULTIPLEDATA not specified}
- Local_Heap_Size :word; {10 Initial local heap size in bytes}
- Stack_Size :word; {12 Initial stack size, in bytes}
- Init_IP :word; {14 Initial entry point}
- Init_CS :word; {16 Index to segment table!'}
- Init_SP :word; {18 Initial stack}
- Init_SS :word; {1A}
- Segment_Table_Entries:word; {1C Number of entries in segment table}
- Mod_Ref_Table_Entries:word; {1E Number of entries in module reference table}
- Non_NameTable_Entries:word; {20 Number of entries in non-resident name table}
- Seg_Table_Offset :word; {22 Offset to segment table, from start of new header}
- Resrc_Table_Offset :word; {24 Offset to resource table}
- Res_Name_Table_Offset:word; {26 Offset to resident name table}
- Mod_Ref_Table_Offset :word; {28 Offset to module reference table}
- Imp_Name_Table_Offset:word; {2A Offset to imported names table}
- Nrs_Name_Table_Offset:longint; {2C Offset to non-resident name table, from BEGINNING of file in bytes}
- Moveable_Entry_Pts :word; {30 Number of moveable entry points}
- Seg_Alignment :word; {32 Log base 2 of segment sector size, defailt=9-->512 bytes}
- Resource_Segments :word; {34 Specifies number of resource segments}
- Op_system :byte; {36 Flags indicate what operating system this file is for 0=unknown, 1=OS/2, 2=Windows}
- Flags2 :byte; {37}
- Fast_Load_Start :word; {38 Specifies start of fast load area}
- Fast_Load_End :word; {3A End of fast load area}
- Reserved2 :word; {3C}
- Win_Version :word; {3E Specifies windows version number}
- end;
-
- SEG_TABLE_TYPE =record
- Offset :word;
- Size :word;
- Attributes :word;
- Alloc :word;
- end;
-
- RES_INFO_TYPE =record
- ResType :word;
- Count :word;
- Reserved :longint;
- end;
-
- RES_NAME_INFO_TYPE =record
- Offset :word;
- Length :word;
- Flags :word;
- ID :word;
- Handle :word;
- Usage :word;
- end;
-
- ENTRY_MOVEABLE_TYPE =record
- Flags :byte;
- INT_3F :word;
- Segment :byte;
- Offset :word;
- end;
-
- ENTRY_FIXED_TYPE =record
- Flags :byte;
- Offset :word;
- end;
-
- REL_INFO_TYPE =record
- rela_type :byte;
- rel_type :byte;
- rofs :word;
- r1 :word;
- r2 :word;
- end;
-
- var
- f :file;
- fname :string;
- fo :text;
- foname :string;
- old_header :OLD_HEADER_TYPE;
- new_header :NEW_HEADER_TYPE;
- seg_table :SEG_TABLE_TYPE;
- i,j,k :word;
- module_name :string;
- resident_name :string;
- res_info :RES_INFO_TYPE;
- res_name_info :RES_NAME_INFO_TYPE;
- resource_name :string;
- seg_align :longint;
- res_align :longint;
- Entry_Moveable :ENTRY_MOVEABLE_TYPE;
- Entry_Fixed :ENTRY_FIXED_TYPE;
- cs_size :word;
- cs_loc :longint;
- rel_count :word;
- rel_info :REL_INFO_TYPE;
- IMName :array[1..20] of string;
-
- function hex(w:word):string;
- const h:array[0..15] of char=('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
- begin
- hex:=h[w div 4096] + h[(w div 256) and 15] + h[(w div 16) and 15] + h[w and 15];
- end;
-
- function imported_name(j:word):string;
- var
- s :string;
- n,i :word;
- begin
- n:=1;
- for i:=1 to j do
- begin
- seek(f,old_header.New_Header_Offset+new_header.Imp_Name_Table_Offset+n);
- blockread(f,s,255);
- if ord(s[0])>0 then n:=n+ord(s[0])+1;
- end;
- imported_name:=s;
- end;
-
- begin
- fname:=ParamStr(1);
- if ParamCount<>2 then AssignCRT(fo) else
- begin
- foname:=ParamStr(2);
- assign(fo,foname);
- end;
- rewrite(fo);
- assign(f,fname);
- reset(f,1); {open with 1 byte block}
- blockread(f,old_header,sizeof(old_header));
- if ParamCount<>2 then ClrScr;
- if old_header.ID_Word<>ord('M')+256*ord('Z') then
- begin
- writeln(fo,'This is not an EXE file!!');
- halt;
- end;
- if old_header.Reloc_Table_Offset>=$40 then
- begin
- seek(f,old_header.New_Header_Offset);
- blockread(f,new_header,sizeof(new_header));
- if ParamCount<>2 then clrscr;
- with new_header do {Display header info}
- begin
- writeln(fo,'Initial CS:IP = #',Init_CS,':',hex(Init_IP),'H');
- writeln(fo,'Initial SS:SP = #',Init_SS,':',hex(Init_SP),'H Size = ',Stack_Size);
- writeln(fo,'Segment table entries = ',Segment_Table_Entries);
- writeln(fo,'Module reference table entries = ',Mod_Ref_Table_Entries);
- writeln(fo,'Moveable entry points = ',Moveable_Entry_Pts);
- writeln(fo,'Resource segments = ',Resource_Segments);
- writeln(fo,'Automatic data segment = ',Automatic_Data_Seg);
- writeln(fo,'Fast load offset = ',Fast_Load_Start);
- end;
- writeln(fo);
- writeln(fo,'Modules referenced: ');
- for i:=1 to new_header.Mod_Ref_Table_Entries do
- begin
- seek(f,old_header.New_Header_Offset+new_header.Mod_Ref_Table_Offset+2*(i-1));
- blockread(f,j,2);
- seek(f,old_header.New_Header_Offset+new_header.Imp_Name_Table_Offset+j);
- blockread(f,module_name,256);
- writeln(fo,' ',i,': ',module_name);
- IMName[i]:=module_name;
- end;
- writeln(fo);
- write(fo,'Resident names: ');
- j:=0;
- repeat
- seek(f,old_header.New_Header_Offset+new_header.Res_Name_Table_Offset+j);
- blockread(f,resident_name,256);
- j:=j+ord(resident_name[0])+2;
- write(fo,resident_name,' ');
- until resident_name[0]=#0;
- writeln(fo);
- writeln(fo,'Non-resident names: ');
- j:=0;
- repeat
- seek(f,new_header.NRS_Name_Table_Offset+j);
- blockread(f,resident_name,256);
- j:=j+ord(resident_name[0])+3;
- k:=ord(resident_name[ord(resident_name[0])+1])
- +256*ord(resident_name[ord(resident_name[0])+2]);
- writeln(fo,k:5,' ',resident_name);
- until resident_name[0]=#0;
- writeln(fo);
- seg_align:=1;
- if new_header.Seg_Alignment<>0 then for i:=1 to new_header.Seg_Alignment do seg_align:=2*seg_align
- else seg_align:=512;
- writeln(fo,'Segments: (Alignment=',seg_align,'(',new_header.Seg_Alignment,'))');
- writeln(fo,'Offset Length Alloc Size Attributes');
- for i:=1 to new_header.Segment_Table_Entries do
- begin
- seek(f,old_header.New_Header_Offset+new_header.Seg_Table_Offset+8*(i-1));
- blockread(f,seg_table,sizeof(seg_table));
- write(fo,seg_table.offset:5,seg_table.size:9,seg_table.alloc:13,' ');
- if seg_table.attributes and 1 = 1 then write(fo,'DATA ') else write(fo,'CODE ');
- if seg_table.attributes and 2 = 2 then write(fo,'Allocated ');
- if seg_table.attributes and 4 = 4 then write(fo,'Loaded ');
- if seg_table.attributes and 16 = 16 then write(fo,'Moveable ') else write(fo,'Fixed ');
- if seg_table.attributes and 32 = 32 then write(fo,'Shareable ');
- if seg_table.attributes and 64 = 64 then write(fo,'Preload ');
- if seg_table.attributes and 128 = 128 then write(fo,'Exec_Only/Read_Only ');
- if seg_table.attributes and 256 = 256 then write(fo,'Contains_Rel_Data ');
- if seg_table.attributes and 4096 = 4096 then write(fo,'Discardable ');
- writeln(fo);
- if i=New_Header.Init_CS then
- begin
- cs_size:=seg_table.size;
- cs_loc:=seg_table.offset*seg_align;
- end;
- end;
- writeln(fo);
- writeln(fo,'Entry table:');
- seek(f,old_header.New_Header_Offset+new_header.Entry_Table_Offset);
- repeat
- blockread(f,j,2);
- if j shr 8 = $FF then
- begin
- writeln(fo,'Moveable:');
- for i:=1 to j and $FF do
- begin
- blockread(f,Entry_Moveable,sizeof(Entry_Moveable));
- writeln(fo,Entry_Moveable.Segment,':',hex(Entry_Moveable.Offset));
- end;
- end;
- if j shr 8 = $FE then
- begin
- writeln(fo,'Constant:');
- end;
- if not (j shr 8 in [0,$FE,$FF]) then
- begin
- writeln(fo,'Fixed: (',j and $FF,')');
- for i:=1 to j and $FF do
- begin
- blockread(f,Entry_Fixed,sizeof(Entry_Fixed));
- writeln(fo,j shr 8,':',hex(Entry_Fixed.Offset));
- end;
- end;
- until (j and $FF) = 0;
- writeln(fo);
- writeln(fo,'Relocation data: ');
- seek(f,cs_loc+cs_size);
- blockread(f,rel_count,2);
- for i:=1 to rel_count do
- begin
- blockread(f,rel_info,sizeof(rel_info));
- write(fo,rel_info.rela_type:3,' ',rel_info.rofs:5,' ');
- case rel_info.rel_type of
- 0 : write(fo,'Internal Ref ');
- 1 : begin
- write(fo,'Imported ord ');
- write(fo,IMName[rel_info.r1],'.',rel_info.r2);
- end;
- 2 : write(fo,'Imported Name ');
- 3 : write(fo,'OS FIXUP ');
- else write(fo,'UNKNOWN REL TYP');
- end;
- writeln(fo);
- end;
- end
- else writeln(fo,'This is a standard DOS EXE file.');
-
- writeln(fo);
- writeln(fo,'Press any key to continue.');
- if ParamCount<>2 then if ReadKey=' ' then ;
- close(fo);
- close(f);
- end.
-